from twisted.internet import reactor, protocol, stdio
from Location import *
import time
import sys
from twisted.protocols import basic
from sys import stdout
import thread

dispatcher = {}
request = {}
test_sequence = []
test_state = 0
user_seq = 0


def Send_RegistSyn(client) :	
	global user_seq
	req = RegistSyn()	
	req.seq = user_seq
	client.send(req)
	print 'Send_RegistSyn'
	
def Read_RegistAck(client, recv_data) :
	
	ack = RegistAck()
	ack.Load(recv_data)
	print '============================================================'
	print 'Read_RegistAck'
	print 'seq : ' + str(ack.seq)	
	print 'result : ' + str(ack.result)	
	print 'strError : ' + ack.strError
	print '============================================================'
	
def Send_UnRegistSyn(client) :	
	global user_seq
	req = UnRegistSyn()
	req.seq = user_seq
	client.send(req)
	print 'Send_UnRegistSyn'
	
def Read_UnRegistAck(client, recv_data) :	
	ack = RegistAck()
	ack.Load(recv_data)
	print '============================================================'
	print 'Read_UnRegistAck'
	print 'seq : ' + str(ack.seq)	
	print 'result : ' + str(ack.result)	
	print 'strError : ' + ack.strError
	print '============================================================'
	#time.sleep(1)
	#client.rewand()

		
def Send_ChatSyn(client, receiver, msg):
	global user_seq
	req = ChatSyn()
	req.sender_seq = user_seq
	req.receiver_seq = receiver
	req.msgs = msg
	client.send(req)
	print 'ChatSyn'
	
	
def Read_ChatSyn(client, recv_data) :	
	ack = ChatSyn()
	ack.Load(recv_data)
	print '============================================================'
	print 'Read_ChatSyn'
	print 'sender_seq : ' + str(ack.sender_seq)	
	print 'receiver_seq : ' + str(ack.receiver_seq)	
	print 'msgs : ' + ack.msgs
	print '============================================================'
	
def Read_ChatAck(client, recv_data) :	
	ack = ChatSyn()
	ack.Load(recv_data)
	print '============================================================'
	print 'Read_ChatAck'
	print 'sender_seq : ' + str(ack.sender_seq)	
	print 'receiver_seq : ' + str(ack.receiver_seq)	
	#print 'result : ' + ack.result
	print '============================================================'

def Send_RecallSyn(client, receiver) :
	global user_seq
	req = RecallSyn()
	req.sender_seq = user_seq
	req.receiver_seq = receiver
	req.ip = '127.0.0.1'
	req.port = 20001
	client.send(req)	
	
def Read_RecallSyn(client, recv_data) :
	ack = RecallSyn()
	ack.Load(recv_data)
	print '============================================================'
	print 'Read_RecallSyn'
	print 'sender_seq : ' + str(ack.sender_seq)	
	print 'receiver_seq : ' + str(ack.receiver_seq)	
	print 'ip : ' + ack.ip
	print 'port : ' + str(ack.port)
	print '============================================================'
	
def Read_RecallAck(client, recv_data) :
	ack = RecallAck()
	ack.Load(recv_data)
	print '============================================================'
	print 'Read_RecallAck'
	print 'sender_seq : ' + str(ack.sender_seq)	
	print 'receiver_seq : ' + str(ack.receiver_seq)
	print 'result : ' + str(ack.result)
	print '============================================================'
	
test_sequence.append(Send_RegistSyn)
test_sequence.append(Send_UnRegistSyn)

request[RegistSyn.MSG_ID] = Send_RegistSyn
request[UnRegistSyn.MSG_ID] = Send_UnRegistSyn
request[ChatSyn.MSG_ID] = Send_ChatSyn
request[RecallSyn.MSG_ID] = Send_RecallSyn

dispatcher[RegistAck.MSG_ID] = Read_RegistAck
dispatcher[UnRegistAck.MSG_ID] = Read_UnRegistAck
dispatcher[ChatSyn.MSG_ID] = Read_ChatSyn
dispatcher[ChatAck.MSG_ID] = Read_ChatAck
dispatcher[RecallSyn.MSG_ID] = Read_RecallSyn
dispatcher[RecallAck.MSG_ID] = Read_RecallAck

def console(threadName, client) :
	while True :
		value = input('msg id :')
		#print 'value : ' + str(value)	
		#request[value](client)
		if (value == 602):
			Send_RegistSyn(client)
		elif (value == 604):
			Send_UnRegistSyn(client)
		elif (value == 606):
			receiver = input('receiver :')
			msg = raw_input('msg :')
			Send_ChatSyn(client, receiver, msg)		
		elif (value == 608):
			receiver = input('receiver :')
			Send_RecallSyn(client, receiver)

class Client(protocol.Protocol): 
	recv_data = ''	
	def connectionMade(self): 
		global test_sequence, test_state
		#test_sequence[test_state](self)		
		Send_RegistSyn(self)
		thread.start_new_thread(console, ('AA',self))

	def connectionLost(self, reason): 	
		print "connection lost" 

	def dataReceived(self, data) :
		# length of total(include header) : 4byte
		# tag_idl : 4byre
		# data 
		self.recv_data += data
		while len(self.recv_data) :
			global dispatcher, test_sequence, test_state
			if(len(self.recv_data) < 6) :
				print 'received data size is under \'length size\''
				break
		
			recv_bytes_tobe = int(struct.unpack('h', self.recv_data[1:3])[0]) + 3
			if(len(self.recv_data) < recv_bytes_tobe) :
				print 'received data size is under \'total size\''
				break;

			tag_id = struct.unpack('h', self.recv_data[4:6])[0]; 
			recv_data = self.recv_data[6:recv_bytes_tobe] 
			self.recv_data = self.recv_data[recv_bytes_tobe:]
			print 'tag_id : ' + str(tag_id)
			test_state += 1
			
			dispatcher[tag_id](self, recv_data)
			#console(self)
			#print 'test_state : ' + str(test_state)
			#if test_state < len(test_sequence) :
				#test_sequence[test_state](self)
			
				
			
	def send(self, msg) :
		data = msg.Store()
		send_data  = struct.pack('B', 0xff)
		send_data += struct.pack('h', 3 + len(data))
		send_data += struct.pack('b', 0)
		send_data += struct.pack('h', msg.MSG_ID)
		send_data += data
		self.transport.write(send_data)
	
	def rewand(self) :
		global dispatcher, test_sequence, test_state
		test_state = 0
		print 'rewand test_state : ' + str(test_state)
		#test_sequence[test_state](self)
		#test_state = 1		
		

class ClientFactory(protocol.ClientFactory): 
	protocol = Client 
	def clientConnectionFailed(self, connector, reason): 
		print "Connection failed - goodbye!" 
		reactor.stop() 
	def clientConnectionLost(self, connector, reason): 
		print "Connection lost - goodbye!" 
		reactor.stop() # this connects the protocol to a server runing on port 8000 


		

def main():
	
	global user_seq	
	user_seq = int(sys.argv[1])
	#print 'user_seq : ' + str(user_seq)
	f = ClientFactory()
	
	#stdio.StandardIO(Console(f))
	reactor.connectTCP("localhost", 20001, f)
	 
	reactor.run()
	#thread.start_new_thread(console, ('AA',f.protocol))
	

if __name__ == '__main__': 
	main() 
